# %%
import pandas as pd
url = "https://raw.githubusercontent.com/MicrosoftDocs/mslearn-introduction-to-machine-learning/main/Data/ml-basics/penguins.csv"
df = pd.read_csv(url)

# %%
#printing the first 5 rows of the dataset
print(df.head())

# %%
# Let's visualize the distribution of the penguins species with a bar plot in matplotlib
import matplotlib.pyplot as plt
# 从您已加载的数据中创建物种分布图
# df 是您已经加载的企鹅数据集

# 统计各物种的数量
species_counts = df['Species'].value_counts().sort_index()

# 创建条形图
plt.figure(figsize=(8, 6))
bars = plt.bar(species_counts.index, species_counts.values, color=['skyblue', 'lightcoral', 'lightgreen'])

# 添加标题和标签
plt.title('Distribution of Penguin Species')
plt.xlabel('Species')
plt.ylabel('Count')

# 添加数值标签
for bar in bars:
    height = bar.get_height()
    plt.text(bar.get_x() + bar.get_width()/2., height,
             f'{int(height)}', ha='center', va='bottom')

plt.show()

# %%
# Let's visualize with boxplots how the FlipperLength, CulmenLength and CulmenDepth are distributed for each species
# importing seaborn

import seaborn as sns
# 创建一个图形包含三个子图
fig, axes = plt.subplots(1, 3, figsize=(18, 6))

# 为 FlipperLength 创建箱线图
sns.boxplot(data=df, x='Species', y='FlipperLength', ax=axes[0])
axes[0].set_title('Flipper Length Distribution by Species')
axes[0].set_xlabel('Species')
axes[0].set_ylabel('Flipper Length (mm)')

# 为 CulmenLength 创建箱线图
sns.boxplot(data=df, x='Species', y='CulmenLength', ax=axes[1])
axes[1].set_title('Culmen Length Distribution by Species')
axes[1].set_xlabel('Species')
axes[1].set_ylabel('Culmen Length (mm)')

# 为 CulmenDepth 创建箱线图
sns.boxplot(data=df, x='Species', y='CulmenDepth', ax=axes[2])
axes[2].set_title('Culmen Depth Distribution by Species')
axes[2].set_xlabel('Species')
axes[2].set_ylabel('Culmen Depth (mm)')

# 调整布局防止重叠
plt.tight_layout()

# 显示图形
plt.show()

# %%
# Show rows with missing values
# 方法1: 显示任何列包含缺失值的行
print("所有包含缺失值的行:")
print(df[df.isnull().any(axis=1)])

# %%
# Drop rows with missing values
# 删除包含缺失值的行
df_cleaned = df.dropna()

# 显示删除前后的数据形状
print(f"原始数据形状: {df.shape}")
print(f"删除缺失值后数据形状: {df_cleaned.shape}")
print(f"删除的行数: {df.shape[0] - df_cleaned.shape[0]}")

df=df_cleaned

# %%
# Let's prepare for training:
# 1. Split the data into features and labels
# 2. Split the data into training and test sets

# Split the data into features and labels
# features are CulmenLength, CulmenDepth, FlipperLength
# labels are Species

# 1. 将数据拆分为特征和标签
# 特征为 CulmenLength, CulmenDepth, FlipperLength
# 标签为 Species
features = df[['CulmenLength', 'CulmenDepth', 'FlipperLength']]
labels = df['Species']

# 显示特征和标签的形状
print("特征形状:", features.shape)
print("标签形状:", labels.shape)

# 显示前5行特征
print("\n前5行特征:")
print(features.head())

# 显示前5行标签
print("\n前5行标签:")
print(labels.head())



# %%
# Split the data into training and test sets in a way to have 30% of the data for testing
# 2. 将数据拆分为训练集和测试集
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    features, 
    labels, 
    test_size=0.3,      # 30%的数据用于测试
    random_state=42,    # 设置随机种子以确保结果可重现
    stratify=labels          # 分层抽样，保持训练集和测试集中各类别的比例一致
)

# 5. 显示拆分结果
print("数据拆分结果:")
print(f"训练集特征形状: {X_train.shape}")
print(f"测试集特征形状: {X_test.shape}")
print(f"训练集标签形状: {y_train.shape}")
print(f"测试集标签形状: {y_test.shape}")
print(f"训练集样本数: {len(X_train)} ({len(X_train)/len(df)*100:.1f}%)")
print(f"测试集样本数: {len(X_test)} ({len(X_test)/len(df)*100:.1f}%)")

# 6. 查看训练集和测试集中各类别的分布
print("\n训练集中各类别的分布:")
print(y_train.value_counts().sort_index())
print("\n测试集中各类别的分布:")
print(y_test.value_counts().sort_index())

# %%
# Let's train a Logistic Regression model
# 1. Create a multiclass Logistic Regression model
# 2. Train the model
# Create a multiclass Logistic Regression model

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

# 2. 创建多类逻辑回归模型
# 使用默认参数创建逻辑回归模型
# sklearn的LogisticRegression默认支持多类分类
model = LogisticRegression(
    multi_class='auto',  # 自动选择多类策略
    solver='lbfgs',      # 优化算法
    max_iter=1000        # 最大迭代次数
)

# 3. 训练模型
# 使用训练数据拟合模型
model.fit(X_train, y_train)



# %%
# Let's evaluate the model
# 1. Predict the labels of the test set
# 2. Calculate the accuracy of the model

# 1. 预测测试集的标签
# 使用已训练的模型对测试集进行预测
y_pred = model.predict(X_test)

# 2. 计算模型的准确率
# 导入准确率计算函数
from sklearn.metrics import accuracy_score

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)

# 显示结果
print(f"模型在测试集上的准确率: {accuracy:.4f}")
print(f"模型正确预测了 {accuracy*100:.2f}% 的企鹅种类")

# 可选：显示更详细的分类报告
from sklearn.metrics import classification_report
print("\n详细分类报告:")
print(classification_report(y_test, y_pred))


